use std::{
    hash::{Hash, Hasher},
    sync::atomic::{AtomicU64, Ordering},
    time::SystemTime,
};

#[allow(dead_code)]
pub static GLOABL_IDENTIFY: AtomicU64 = AtomicU64::new(0);

// 申请Gloabl id.
#[allow(dead_code)]
pub fn alloc_gloabl_id() -> u64 {
    GLOABL_IDENTIFY.fetch_add(1, Ordering::Relaxed)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct UniqueID(pub u64, pub u64);

#[allow(dead_code)]
impl UniqueID {
    #[inline]
    pub fn new() -> Self {
        let now = SystemTime::now()
            .duration_since(SystemTime::UNIX_EPOCH)
            .unwrap()
            .as_secs();
        let g_id = GLOABL_IDENTIFY.fetch_add(1, Ordering::Relaxed);
        Self(now, g_id)
    }

    #[inline]
    pub fn new_with_id(id_0: u64, id_1: u64) -> Self {
        Self(id_0, id_1)
    }

    #[inline]
    pub fn crc32(&self) -> u32 {
        let mut h = crc32fast::Hasher::new();
        self.hash(&mut h);
        h.finalize()
    }

    #[inline]
    pub fn crc64(&self) -> u64 {
        let mut h = crc32fast::Hasher::new();
        self.hash(&mut h);
        h.finish()
    }
}

impl std::fmt::Display for UniqueID {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}-{}", self.0, self.1)
    }
}

#[cfg(test)]
mod tests {
    use super::UniqueID;

    #[test]
    fn test_unique_id() {
        let unique_id = UniqueID::new();
        println!("{:#?}", unique_id);
        println!("{} {}", unique_id.crc32(), unique_id.crc64());
        let unique_id = UniqueID::new();
        println!("{:#?}", unique_id);
        println!("{} {}", unique_id.crc32(), unique_id.crc64());
    }
}
